package lvtu.opencv.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import lvtu.opencv.worker.Worker;

import org.apache.commons.codec.net.URLCodec;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.HeadMethod;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * HTTPClient工具类
 * 
 * @author wenbin.gao
 */
public class HttpUtil {

	private static final Logger log = LoggerFactory.getLogger(Worker.class);

    private static int SO_TIMEOUT = 10000;
    private static int CONNECT_TIME_OUT = 10000;

    /**
     * post请求
     * 
     * @param url
     * @param charset
     * @param data
     * @return
     * @throws Exception
     */
    public HttpResult post(String url, String charset, NameValuePair[] data) throws Exception {
        return post(url, charset, data, null);
    }

    /**
     * post 新浪微博请求
     * 
     * @param url
     * @param charset
     * @param data
     * @return
     * @throws Exception
     */
    public HttpResult postWeibo(String url, String charset, NameValuePair[] data, String imageUrl) throws Exception {

        HttpResult httpResult = new HttpResult();
        PostMethod postMethod = new PostMethod(url);
        URLConnection connection = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            Map<String, String> headerMap = new HashMap<String, String>();
            // post.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, SO_TIMEOUT);// 请求超时秒
            HttpMethodParams hmp = new HttpMethodParams();
            hmp.setContentCharset(charset);
            hmp.setSoTimeout(SO_TIMEOUT);

            postMethod.setParams(hmp);

            setRequestHeader(postMethod, headerMap);
            if (imageUrl != null && !"".equals(imageUrl)) {
                log.info("######## imageUrl is : "+imageUrl);
                URL picUrl = new URL(imageUrl);
                connection = picUrl.openConnection();
                is = connection.getInputStream();
                baos = new ByteArrayOutputStream();
                int len = 0;
                byte[] b = new byte[1024];
                while ((len = is.read(b, 0, b.length)) != -1) {
                    baos.write(b, 0, len);
                }
                byte[] buffer = baos.toByteArray();
                Part[] parts = new Part[data.length + 1];
                parts[0] = new FilePart("pic", new ByteArrayPartSource("pic", buffer));
                log.info("buffer : " + buffer);
                if (data != null) {
                    int i = 0;
                    for (NameValuePair nvp : data) {
                        i++;
                        parts[i] = new StringPart(nvp.getName(), nvp.getValue());
                        log.info("nvp.getName() : " + nvp.getName() + "##" + "nvp.getValue() : " + nvp.getValue());
                    }
                }
                MultipartRequestEntity multipartRequestEntity = new MultipartRequestEntity(parts,
                        postMethod.getParams());

                postMethod.setRequestEntity(multipartRequestEntity);

            }else{
                log.info("######## imageUrl is : "+imageUrl);
                postMethod.setRequestBody(data);
            }
            StringBuilder sb = new StringBuilder();
            int result;
            BufferedReader in = null;
            HttpClient httpClient = new HttpClient();
            try {
                httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(CONNECT_TIME_OUT);
                result = httpClient.executeMethod(postMethod);
                in = new BufferedReader(new InputStreamReader(postMethod.getResponseBodyAsStream(), charset));
                String line = null;
                while ((line = in.readLine()) != null) {
                    sb.append(line).append("\r\n");
                }
            } finally {
                if (postMethod != null) {
                    postMethod.releaseConnection();
                }
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        log.error(e.getMessage(), e);
                    }
                    in = null;
                }
                if (is != null) {
                    is.close();
                }
                if (baos != null) {
                    baos.close();
                }
            }
            httpResult.setStateCode(result);
            log.info("############result : " + result);
            httpResult.setContent(sb.toString());
            log.info(sb.toString());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }

        return httpResult;
    }

    /**
     * post请求
     * 
     * @param url
     * @param charset
     * @param data
     * @param headerMap
     * @return
     * @throws Exception
     */
    public HttpResult post(String url, String charset, NameValuePair[] data, Map<String, String> headerMap)
            throws Exception {
        PostMethod post = new PostMethod(url);
        // post.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, SO_TIMEOUT);// 请求超时秒
        HttpMethodParams hmp = new HttpMethodParams();
        hmp.setContentCharset(charset);
        hmp.setSoTimeout(SO_TIMEOUT);
        post.setParams(hmp);
        setRequestHeader(post, headerMap);
        if (data != null) {
            post.setRequestBody(data);
        }
        return getResponseBodyAsStream(post, charset);
    }

    /**
     * post xml
     * 
     * @param url
     * @param charset
     * @param xml
     * @return
     * @throws Exception
     */
    public HttpResult postXml(String url, String charset, String xml) throws Exception {
        return postXml(url, charset, xml, null);
    }

    /**
     * post xml
     * 
     * @param url
     * @param charset
     * @param xml
     * @param headerMap
     * @return
     * @throws Exception
     */
    public HttpResult postXml(String url, String charset, String xml, Map<String, String> headerMap) throws Exception {
        PostMethod post = new PostMethod(url);
        // post.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, SO_TIMEOUT);// 请求超时秒
        HttpMethodParams hmp = new HttpMethodParams();
        hmp.setSoTimeout(SO_TIMEOUT);
        hmp.setContentCharset(charset);
        post.setParams(hmp);
        setRequestHeader(post, headerMap);
        post.setRequestEntity(new StringRequestEntity(xml, "text/xml", charset));
        return getResponseBodyAsStream(post, charset);
    }

    /**
     * post file
     * 
     * @param url
     * @param charset
     * @param data
     * @param parts
     * @return
     * @throws Exception
     */
    public HttpResult postFile(String url, String charset, NameValuePair[] data, Part[] parts) throws Exception {
        return postFile(url, charset, data, parts, null);
    }

    /**
     * post file
     * 
     * @param url
     * @param charset
     * @param data
     * @param parts
     * @param headerMap
     * @return
     * @throws Exception
     */
    public HttpResult postFile(String url, String charset, NameValuePair[] data, Part[] parts,
            Map<String, String> headerMap) throws Exception {
        PostMethod post = new PostMethod(url);
        // post.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, SO_TIMEOUT);// 请求超时秒
        HttpMethodParams hmp = new HttpMethodParams();
        hmp.setContentCharset(charset);
        hmp.setSoTimeout(SO_TIMEOUT);
        post.setParams(hmp);
        setRequestHeader(post, headerMap);
        if (data != null) {
            post.setRequestBody(data);
        }
        if (parts != null) {
            post.setRequestEntity(new MultipartRequestEntity(parts, post.getParams()));
        }
        return getResponseBodyAsStream(post, charset);
    }

//    /**
//     * post file
//     * 
//     * @param url
//     * @param charset
//     * @param data
//     * @param parts
//     * @param headerMap
//     * @return
//     * @throws Exception
//     */
//    public HttpResult postFile(String url, String charset, NameValuePair[] data, Map<String, String> headerMap,
//            File... file) throws Exception {
//        PostMethod post = new PostMethod(url);
//        // post.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, SO_TIMEOUT);// 请求超时秒
//        HttpMethodParams hmp = new HttpMethodParams();
//        hmp.setSoTimeout(SO_TIMEOUT);
//        hmp.setContentCharset(charset);
//        post.setParams(hmp);
//        setRequestHeader(post, headerMap);
//        if (data != null) {
//            post.setRequestBody(data);
//        }
//        Part[] parts = new Part[file.length];
//        for (int i = 0; i < file.length; i++)
//            parts[i] = new CustomFilePart(file[i].getName(), file[i]);
//        if (parts != null) {
//            post.setRequestEntity(new MultipartRequestEntity(parts, post.getParams()));
//        }
//        return getResponseBodyAsStream(post, charset);
//    }

    /**
     * post file
     * 
     * @param url
     * @param charset
     * @param filePathName
     * @return
     * @throws Exception
     */
    public HttpResult postFile(String url, String charset, String filePathName) throws Exception {
        PostMethod post = new PostMethod(url);
        // post.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, SO_TIMEOUT);// 请求超时秒
        HttpMethodParams hmp = new HttpMethodParams();
        hmp.setSoTimeout(SO_TIMEOUT);
        hmp.setContentCharset(charset);
        post.setParams(hmp);
        File file = new File(filePathName);
        post.setRequestEntity(new InputStreamRequestEntity(new FileInputStream(file), file.length(),
                "application/octet-stream"));
        return getResponseBodyAsStream(post, charset);
    }

    /**
     * get 请求
     * 
     * @param url
     * @param charset
     * @return
     * @throws Exception
     */
    public HttpResult get(String url, String charset) throws Exception {
        return get(url, charset, null);
    }

    /**
     * get 请求
     * 
     * @param url
     * @param charset
     * @return
     * @throws Exception
     */
    public HttpResult get(String url, String charset, int soTimeout) throws Exception {
        return get(url, charset, null, soTimeout);
    }

    /**
     * @param url
     * @param charset
     * @return
     * @throws Exception
     */
    public HttpResult getByProxy(String url, String charset) throws Exception {
        Map<String, String> headerMap = new HashMap<String, String>();
        headerMap.put("Accept-Language", "zh-cn");
        headerMap.put("User-Agent", " Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.2)");
        headerMap.put("Connection", " Keep-Alive");
        headerMap.put("Cookie", "iscookies=0");
        return getByProxy(url, charset, headerMap);
    }

    /**
     * @param url
     * @param charset
     * @param headerMap
     * @return
     * @throws Exception
     */
    public HttpResult getByProxy(String url, String charset, Map<String, String> headerMap) throws Exception {
        GetMethod get = new GetMethod(url);
        // get.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, SO_TIMEOUT);// 请求超时秒
        HttpMethodParams hmp = new HttpMethodParams();
        hmp.setContentCharset(charset);
        hmp.setSoTimeout(SO_TIMEOUT);
        hmp.setParameter("http.protocol.cookie-policy", CookiePolicy.BROWSER_COMPATIBILITY);
        setRequestHeader(get, headerMap);
        get.setParams(hmp);
        return getResponseBodyAsStreamByProxy(get, charset);
    }

    /**
     * @param httpMethod
     * @param charset
     * @return
     * @throws Exception
     */
    private HttpResult getResponseBodyAsStreamByProxy(HttpMethod httpMethod, String charset) throws Exception {
        StringBuilder sb = new StringBuilder();
        int result;
        BufferedReader in = null;
        HttpClient httpClient = new HttpClient();
        try {
            // 221.130.7.232 80
            String proxyHost = "221.130.7.232";
            int proxyPort = 80;
            httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(CONNECT_TIME_OUT);
            httpClient.getHostConfiguration().setProxy(proxyHost, proxyPort);
            result = httpClient.executeMethod(httpMethod);
            in = new BufferedReader(new InputStreamReader(httpMethod.getResponseBodyAsStream(), charset));
            String line = null;
            while ((line = in.readLine()) != null) {
                sb.append(line).append("\r\n");
            }
        } finally {
            if (httpMethod != null) {
                httpMethod.releaseConnection();
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
                in = null;
            }
        }
        HttpResult httpResult = new HttpResult();
        httpResult.setStateCode(result);
        httpResult.setContent(sb.toString());
        return httpResult;
    }

    /**
     * get 请求
     * 
     * @param url
     * @param charset
     * @param headerMap
     * @return
     * @throws Exception
     */
    public HttpResult get(String url, String charset, Map<String, String> headerMap) throws Exception {
        // GetMethod get = new GetMethod(url);
        // // get.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, SO_TIMEOUT);// 请求超时秒
        // HttpMethodParams hmp = new HttpMethodParams();
        // hmp.setContentCharset(charset);
        // hmp.setSoTimeout(SO_TIMEOUT);
        // hmp.setParameter("http.protocol.cookie-policy", CookiePolicy.BROWSER_COMPATIBILITY);
        // setRequestHeader(get, headerMap);
        // get.setParams(hmp);
        // return getResponseBodyAsStream(get, charset);
        return this.get(url, charset, headerMap, SO_TIMEOUT);
    }

    /**
     * get 请求
     * 
     * @param url
     * @param charset
     * @param headerMap
     * @return
     * @throws Exception
     */
    public HttpResult get(String url, String charset, Map<String, String> headerMap, int soTimeout) throws Exception {
        GetMethod get = new GetMethod(url);
        // get.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, SO_TIMEOUT);// 请求超时秒
        HttpMethodParams hmp = new HttpMethodParams();
        hmp.setContentCharset(charset);
        hmp.setSoTimeout(soTimeout);
        hmp.setParameter("http.protocol.cookie-policy", CookiePolicy.BROWSER_COMPATIBILITY);
        setRequestHeader(get, headerMap);
        get.setParams(hmp);
        return getResponseBodyAsStream(get, charset);
    }

    /**
     * head 请求
     * 
     * @param url
     * @return
     * @throws Exception
     */
    public int head(String url) throws Exception {
        return head(url, null);
    }

    /**
     * head 请求
     * 
     * @param url
     * @param headerMap
     * @return
     * @throws Exception
     */
    public int head(String url, Map<String, String> headerMap) throws Exception {
        HeadMethod head = new HeadMethod(url);
        int stateCode = 0;
        try {
            HttpClient httpClient = new HttpClient();
            httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(CONNECT_TIME_OUT);
            setRequestHeader(head, headerMap);
            stateCode = httpClient.executeMethod(head);
        } finally {
            if (head != null) {
                head.releaseConnection();
            }
        }
        return stateCode;
    }

    /**
     * 下载文件到指定路径
     * 
     * @param url
     * @param savePathFileName
     * @throws Exception
     */
    public void getAndSaveData(String url, String savePathFileName) throws Exception {
        GetMethod httpMethod = new GetMethod(url);
        // httpMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, SO_TIMEOUT);// 请求超时秒
        HttpMethodParams hmp = new HttpMethodParams();
        hmp.setSoTimeout(SO_TIMEOUT);
        httpMethod.setParams(hmp);
        BufferedInputStream in = null;
        BufferedOutputStream fos = null;
        File file = null;
        try {
            HttpClient httpClient = new HttpClient();
            httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(CONNECT_TIME_OUT);
            file = new File(savePathFileName);
            file.getParentFile().mkdirs();
            fos = new BufferedOutputStream(new FileOutputStream(file));
            int result = httpClient.executeMethod(httpMethod);
            if (result == 200 || result == 301 || result == 302) {
                in = new BufferedInputStream(httpMethod.getResponseBodyAsStream());
                byte[] b = new byte[4096];
                int count;
                while ((count = in.read(b)) > 0) {
                    fos.write(b, 0, count);
                }
                fos.flush();
            } else {
                throw new Exception("出错，错误http状态代码:" + result + "  url=" + url + "  savePathFileName="
                        + savePathFileName);
            }
        } finally {
            if (httpMethod != null) {
                httpMethod.releaseConnection();
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
                in = null;
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }
                fos = null;
            }
            if (file != null) {
                file = null;
            }
        }
    }

    public int postData(PostMethod filePost) {
        int i = -1;
        try {
            HttpClient httpClient = new HttpClient();
            httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(CONNECT_TIME_OUT);
            i = httpClient.executeMethod(filePost);// 执行上传
        } catch (HttpException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (filePost != null) {
                filePost.releaseConnection();
            }
        }
        return i;
    }

    /**
     * 设置请求头
     * 
     * @param method
     * @param map
     */
    private void setRequestHeader(HttpMethod method, Map<String, String> map) {
        // method.setRequestHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE
        // 6.0; Windows NT 5.1; SV1)");
        if (map != null) {
            for (Map.Entry<String, String> m : map.entrySet()) {
                method.setRequestHeader(m.getKey(), m.getValue());
            }
        }
    }

    private HttpResult getResponseBodyAsStream(HttpMethod httpMethod, String charset) throws Exception {
        StringBuilder sb = new StringBuilder();
        int result;
        BufferedReader in = null;
        HttpClient httpClient = new HttpClient();
        try {
            httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(CONNECT_TIME_OUT);
            result = httpClient.executeMethod(httpMethod);
            in = new BufferedReader(new InputStreamReader(httpMethod.getResponseBodyAsStream(), charset));
            String line = null;
            while ((line = in.readLine()) != null) {
                sb.append(line).append("\r\n");
            }
        } finally {
            if (httpMethod != null) {
                httpMethod.releaseConnection();
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
                in = null;
            }
        }
        HttpResult httpResult = new HttpResult();
        httpResult.setStateCode(result);
        httpResult.setContent(sb.toString());
        return httpResult;
    }

    public static String doFormUrlEncode(NameValuePair[] pairs, String charset) throws UnsupportedEncodingException {
        StringBuilder buf = new StringBuilder();
        for (int i = 0; i < pairs.length; i++) {
            URLCodec codec = new URLCodec();
            NameValuePair pair = pairs[i];
            if (pair.getName() != null) {
                if (i > 0) {
                    buf.append("&");
                }
                buf.append(codec.encode(pair.getName(), charset));
                buf.append("=");
                if (pair.getValue() != null) {
                    buf.append(codec.encode(pair.getValue(), charset));
                }
            }
        }
        return buf.toString();
    }

    public static NameValuePair[] getToPost(String url, boolean isEncode) {
        NameValuePair[] nvp = null;
        try {
            String[] array = url.split("\\?");
            if (array.length > 1 && array[1].trim().length() > 0) {
                url = array[0];
                String params = array[1];
                String[] paramList = params.split("&");
                nvp = new NameValuePair[paramList.length];
                for (int i = 0; i < paramList.length; i++) {
                    NameValuePair n = new NameValuePair();
                    String[] param = paramList[i].split("=");
                    if (param != null && param.length > 0) {
                        n.setName(param[0]);
                        if (isEncode) {
                            n.setValue(param.length > 1 ? URLEncoder.encode(param[1], "utf-8") : "");
                        } else {
                            n.setValue(param.length > 1 ? param[1] : "");
                        }

                        nvp[i] = n;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return nvp;
    }

    public static String getPostUrl(String url) {
        return url != null && url.indexOf("?") > -1 ? url.substring(0, url.indexOf("?")) : url;
    }

    public static void main(String[] args) {
        // String url = "http://api.user.qunar.com/api/login?signal=&username=iphone&password=123456";
        // NameValuePair[] nvp = getToPost(url, false);
        // url = getPostUrl(url);
        // if (nvp != null) {
        // for (NameValuePair n : nvp) {
        // System.out.println(n.getName() + "=" + n.getValue());
        // }
        // }
        // System.out.println(url);
        URLConnection connection = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        String imageUrl = "http://img1.qunarzz.com/wugc/p133/201301/30/cc371ef7ec96d06893835fbb.jpg";
        URL picUrl;
        try {
            picUrl = new URL(imageUrl);
            connection = picUrl.openConnection();
            is = connection.getInputStream();
            baos = new ByteArrayOutputStream();
            int len = 0;
            byte[] b = new byte[1024];
            while ((len = is.read(b, 0, b.length)) != -1) {
                baos.write(b, 0, len);
            }
            byte[] buffer = baos.toByteArray();
            log.info("buffer : " + buffer);

            NameValuePair[] nvps = new NameValuePair[5];
            String access_token = "2.00YM34DDCNZvqB6fb2ce5b48pi23DE";
            nvps[0] = new NameValuePair("access_token", access_token);
            Integer visible = 0;// 微博的可见性，0：所有人能看，1：仅自己可见，2：密友可见，3：指定分组可见，默认为0。
            nvps[1] = new NameValuePair("visible", String.valueOf(visible));
            nvps[2] = new NameValuePair("lat", "");
            nvps[3] = new NameValuePair("long", "");
            try {
                nvps[4] = new NameValuePair("status", URLEncoder.encode("content" + Math.random(), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                nvps[4] = new NameValuePair("status", "");
            }
            HttpUtil hu = new HttpUtil();
            String sina_upload_url = "https://upload.api.weibo.com/2/statuses/upload.json";
            hu.postWeibo(sina_upload_url, "utf-8", nvps, imageUrl);
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}
